#ifndef MDS_CELLS_INCLUDED
#define MDS_CELLS_INCLUDED 1

#include "../vector.h"
#include "../pnode.h"


#define MDS_CELL_MAX_NEIGHBORS (3*3*3-1)
typedef struct mds_cell_
{
	mds_pnode            *first;                             /*!< first node          */
	size_t                num_neighbors;                     /*!< current  #neighbors */
	struct mds_cell_     *neighbors[MDS_CELL_MAX_NEIGHBORS]; /*!< max 3D neighbors    */
	Real V; /*!< partial potential */
	Real W; /*!< partial virial    */
	size_t label; /*!< uniq label */
}
mds_cell;

#define MDS_THREAD_MAX 64

/** \brief cells manager.
 */
typedef struct 
{
	mds_cell ***array;   /**< 3D array of mds_cell */
	size_t      count;   /**< total number         */
	mds_uvector num;     /**< cells/dimension      */
	mds_vector  length;  /**< one cell sizes       */
	mds_vector  offset;  /**< box/2                */
	mds_vector  factor;  /**< 1/length             */
	size_t      level;   /**< parallelism          */
	size_t      enter[MDS_THREAD_MAX]; /**< enter cell index */
	size_t      leave[MDS_THREAD_MAX]; /**< leave cell index  */
}
mds_cells;

#define MDS_CELLS_INIT { NULL, 0, {0,0,0}, MDS_VECTOR_INIT, MDS_VECTOR_INIT, MDS_VECTOR_INIT }

size_t mds_cells_count1( Real *Lc, const Real L, const Real r_c );
size_t mds_cells_count( mds_uvector *cells_per_dimension, mds_vector *cells_size, const mds_vector *box, const Real sigma_c );

int    mds_cells_load( mds_cells *cells, const mds_vector *box, const Real r_c );
void   mds_cells_quit( mds_cells *cells);
size_t mds_cells_link( mds_cells *cells, const mds_uvector *pbc );


/** \brief build lists for every cells */
void   mds_cells_dispatch(mds_cells         *cells, 
						  const mds_vector  *positions, 
						  mds_pnode         *particle_nodes,
						  size_t             num_particles);


#endif
